Add new format 'skyforce'.
authoroliskoli <oliskoli>
Thu, 30 Oct 2008 22:38:19 +0000 (22:38 +0000)
committeroliskoli <oliskoli>
Thu, 30 Oct 2008 22:38:19 +0000 (22:38 +0000)
Makefile.in
skyforce.c [new file with mode: 0644]
testo
vecs.c

index 5bf16d6d5bcf537c3ef8f7cd574bbba6984c86f8..52818210cbdfb189ca0315f5c92f6e70b2a7ffad 100644 (file)
@@ -61,7 +61,7 @@ ALL_FMTS=$(MINIMAL_FMTS) gtm.o gpsutil.o pcx.o cetus.o copilot.o \
        ggv_log.o g7towin.o garmin_gpi.o lmx.o random.o xol.o dg-100.o \
        navilink.o mtk_logger.o ik3d.o osm.o destinator.o exif.o vidaone.o \
        igo8.o gopal.o humminbird.o mapasia.o gnav_trl.o navitel.o ggv_ovl.o \
-       jtr.o sbp.o mmo.o
+       jtr.o sbp.o mmo.o skyforce.o
 
 FMTS=@FMTS@
 
@@ -752,6 +752,9 @@ session.o: session.c defs.h config.h queue.h gbtypes.h zlib/zlib.h \
 shape.o: shape.c defs.h config.h queue.h gbtypes.h zlib/zlib.h \
   zlib/zconf.h gbfile.h cet.h cet_util.h inifile.h session.h \
   shapelib/shapefil.h
+skyforce.o: skyforce.c defs.h config.h queue.h gbtypes.h \
+  zlib/zlib.h zlib/zconf.h gbfile.h cet.h cet_util.h inifile.h session.h \
+  pdbfile.h
 smplrout.o: smplrout.c defs.h config.h queue.h gbtypes.h zlib/zlib.h \
   zlib/zconf.h gbfile.h cet.h cet_util.h inifile.h session.h filterdefs.h \
   grtcirc.h
diff --git a/skyforce.c b/skyforce.c
new file mode 100644 (file)
index 0000000..910f263
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+
+    Support for SkymapII / SkymapIIIC & KMD150 ascii files
+
+    Copyright (C) 2008 Olaf Klein, o.b.klein@gpsbabel.org
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+
+#include "defs.h"
+#include <ctype.h>
+#include <time.h>
+#include "strptime.h"
+
+
+#define MYNAME "skyforce"
+
+
+static
+arglist_t skyforce_args[] = {
+       ARG_TERMINATOR
+};
+
+static gbfile *fin, *fout;
+static int rte_num, wpt_num;
+static short_handle short_h;
+static const waypoint *prev_wpt;
+
+
+static waypoint *
+skyforce_parse_coords(const char *str)
+{
+       waypoint *wpt;
+
+       if (strlen(str) < 38) fatal(MYNAME ": Incomplete line!\n");
+
+       wpt = waypt_new();
+
+       wpt->latitude = atof(str + 21);
+       if (str[20] == 'S') wpt->latitude = -wpt->latitude;
+       wpt->latitude = ddmm2degrees(wpt->latitude);
+
+       wpt->longitude = atof(str + 30);
+       if (str[29] == 'W') wpt->longitude = -wpt->longitude;
+       wpt->longitude = ddmm2degrees(wpt->longitude);
+
+       return wpt;
+}
+
+
+static waypoint *
+skyforce_parse_wpt(const char *str, int *rte_num)
+{
+       waypoint *wpt;
+
+       wpt = skyforce_parse_coords(str);
+       if (wpt == NULL) return NULL;
+
+       wpt->shortname = lrtrim(xstrndup(str + 10, 9));
+
+       if (rte_num) *rte_num = atoi(str + 2);
+
+       return wpt;
+}
+
+
+static waypoint *
+skyforce_parse_trk(const char *str)
+{
+       char *cx;
+       struct tm tm;
+       char buf[15];
+       int len;
+
+       waypoint *wpt;
+
+       wpt = skyforce_parse_coords(str);
+       if (wpt == NULL) return NULL;
+
+       memset(&tm, 0, sizeof(tm));
+       strncpy(buf, str + 2, sizeof(buf) - 1);
+
+       cx = strptime(buf, "%d%m%y  %H%M%S ", &tm);
+       if ((cx != NULL) && (*cx != '\0'))
+               fatal(MYNAME ": Could not parse date string (%s - %s).\n", buf, cx);
+
+       wpt->creation_time = mkgmtime(&tm);
+
+       len = strlen(str);
+
+       if (len >= 45) WAYPT_SET(wpt, speed, KNOTS_TO_MPS(atof(str + 39)));
+       if (len >= 59) {
+               wpt->altitude = FEET_TO_METERS(atof(str + 54));
+               if (str[53] == '-') wpt->altitude = -wpt->altitude;
+       }
+
+       return wpt;
+}
+
+
+static void
+skyforce_head_disp_cb(const route_head *head)
+{
+       prev_wpt = NULL;
+       if (head->rte_waypt_ct <= 0) return;
+
+       wpt_num = 0;
+       rte_num++;
+
+       if (rte_num > 999) {
+               if (rte_num == 1000) warning(MYNAME ": Can't store more than 999 routes. Some routes skipped!\n");
+               return;
+       }
+}
+
+
+static void
+skyforce_waypt_disp_cb(const waypoint *wpt)
+{
+       char buf[75];   /* long enough for all data types */
+       double lat, lon;
+
+
+       memset(buf, ' ', sizeof(buf));
+       buf[sizeof(buf) - 1] = '\0';
+
+       switch(global_opts.objective) {
+               case wptdata: buf[0] = 'W'; break;
+               case trkdata: buf[0] = 'L'; break;
+               case rtedata: buf[0] = 'R'; break;
+               default: ; /* should never happen */
+       }
+
+       if (global_opts.objective == trkdata) {
+               struct tm tm;
+
+               tm = *gmtime(&wpt->creation_time);
+               strftime(buf + 2, sizeof(buf) - 2, "%d%m%y  %H%M%S    ", &tm);
+       }
+       else {
+               char *name;
+
+               if (rte_num > 999) return;
+
+               wpt_num++;
+               if (wpt_num > 999) {
+                       if (wpt_num == 1000)
+                               warning(MYNAME ": Can't store more than 999 waypoints. Some waypoints skipped!\n");
+                       return;
+               }
+               if (global_opts.synthesize_shortnames)
+                       name = mkshort_from_wpt(short_h, wpt);
+               else
+                       name = mkshort(short_h, wpt->shortname);
+
+               if (global_opts.objective == rtedata)
+                       snprintf(buf + 2, sizeof(buf) - 2, "%03d ", rte_num);
+               snprintf(buf + 6, sizeof(buf) - 6, "%03d %-9s ", wpt_num, name);
+       }
+
+
+       lat = degrees2ddmm(wpt->latitude);
+       buf[20] = (wpt->latitude < 0) ? 'S' : 'N';
+       snprintf(&buf[21], sizeof(buf) - 21, "%06.2f ", fabs(lat));
+
+       lon = degrees2ddmm(wpt->longitude);
+       buf[29] = (wpt->longitude < 0) ? 'W' : 'E';
+       snprintf(&buf[30], sizeof(buf) - 30, "%08.2f ", fabs(lon));
+
+       if (global_opts.objective == trkdata) {
+               double alt, speed;
+
+               if (wpt->altitude == unknown_alt) alt = 0;
+               else alt = METERS_TO_FEET(wpt->altitude);
+               speed = MPS_TO_KNOTS(waypt_speed(prev_wpt, wpt));
+
+               snprintf(&buf[39], sizeof(buf) - 39, "%06.2f 000.00 %c%05d",
+                       speed,
+                       alt < 0 ? '-' : '+', si_round(fabs(alt)));
+       }
+
+       rtrim(buf);
+       gbfprintf(fout, "%s\n", buf);
+
+       prev_wpt = wpt;
+}
+
+/*******************************************************************************
+* %%%        global callbacks called by gpsbabel main process              %%% *
+*******************************************************************************/
+
+static void
+skyforce_rd_init(const char *fname)
+{
+       fin = gbfopen(fname, "r", MYNAME);
+}
+
+
+static void
+skyforce_rd_deinit(void)
+{
+       gbfclose(fin);
+}
+
+
+static void
+skyforce_read(void)
+{
+       char *str;
+       route_head *rte, *trk;
+
+       wpt_num = 0;
+       rte = trk = NULL;
+       rte_num = -1;
+
+       while ((str = gbfgetstr(fin))) {
+
+               waypoint *wpt;
+               int i;
+
+               str = lrtrim(str);
+               if (*str == '\0') continue;
+
+               switch(*str) {
+
+                       case 'W':
+                               wpt = skyforce_parse_wpt(str, NULL);
+                               if (wpt == NULL) continue;
+                               waypt_add(wpt);
+                               break;
+
+                       case 'R':
+                               wpt = skyforce_parse_wpt(str, &i);
+                               if (wpt == NULL) continue;
+
+                               if (i != rte_num) {
+                                       rte_num = i;
+                                       rte = NULL;
+                               }
+
+                               if (rte == NULL) {
+                                       rte = route_head_alloc();
+                                       route_add_head(rte);
+                                       rte->rte_num = rte_num;
+                               }
+                               route_add_wpt(rte, wpt);
+                               break;
+
+                       case 'L':
+                               wpt = skyforce_parse_trk(str);
+                               if (wpt == NULL) continue;
+                               if (trk == NULL) {
+                                       trk = route_head_alloc();
+                                       track_add_head(trk);
+                               }
+                               track_add_wpt(trk, wpt);
+                               break;
+
+                       default:
+                               fatal(MYNAME ": Invalid line marker '%c'!\n", *str);
+               }
+       }
+}
+
+
+static void
+skyforce_wr_init(const char *fname)
+{
+       fout = gbfopen(fname, "w", MYNAME);
+
+       short_h = mkshort_new_handle();
+
+       setshort_length(short_h, 9);
+       setshort_badchars(short_h, "\r\n\t");
+       setshort_mustupper(short_h, 1);
+       setshort_mustuniq(short_h, 1);
+       setshort_whitespace_ok(short_h, 0);
+       setshort_repeating_whitespace_ok(short_h, 0);
+
+       wpt_num = 0;
+       rte_num = 0;
+}
+
+
+static void
+skyforce_wr_deinit(void)
+{
+       mkshort_del_handle(&short_h);
+       gbfclose(fout);
+}
+
+
+static void
+skyforce_write(void)
+{
+       switch(global_opts.objective) { /* We can only write one data type at a time */
+
+               case wptdata:
+                       setshort_defname(short_h, "WPT");
+                       waypt_disp_all(skyforce_waypt_disp_cb);
+                       break;
+
+               case rtedata:
+                       setshort_defname(short_h, "RTE");
+                       setshort_mustuniq(short_h, 0);
+                       route_disp_all(skyforce_head_disp_cb, NULL, skyforce_waypt_disp_cb);
+                       break;
+
+               case trkdata:
+                       track_disp_all(skyforce_head_disp_cb, NULL, skyforce_waypt_disp_cb);
+                       break;
+
+               case posndata:
+                       fatal(MYNAME ": Realtime positioning not supported.\n");
+                       break;
+
+               default:
+                       fatal(MYNAME ": Unknown data mode!\n");
+       }
+}
+
+
+/**************************************************************************/
+
+ff_vecs_t skyforce_vecs = {
+       ff_type_file,
+       FF_CAP_RW_ALL,  /* read and write waypoints, tracks and routes*/
+       skyforce_rd_init,
+       skyforce_wr_init,
+       skyforce_rd_deinit,
+       skyforce_wr_deinit,
+       skyforce_read,
+       skyforce_write,
+       NULL,
+       skyforce_args,
+       CET_CHARSET_ASCII, 1
+};
+
+/**************************************************************************/
diff --git a/testo b/testo
index 577aa53ffe972f2c217f06d6d8e06e0d5a71a1cd..102d33563930cdcb996312e55b64b37c961a3d67 100755 (executable)
--- a/testo
+++ b/testo
@@ -9,7 +9,7 @@ export MALLOC_CHECK_
 
 PNAME=${PNAME:-./gpsbabel}
 DIFF=${DIFF:-diff}
-BASEPATH=$(dirname $0)
+BASEPATH=`dirname $0`
 REFERENCE=${BASEPATH}/reference
 # OD=${OD:-od -Ax -txC -v}
 if [ -x /usr/bin/hexdump ] ; then
@@ -1527,5 +1527,21 @@ compare ${REFERENCE}/memory-map~mmo.gpx ${TMPDIR}/memory-map~mmo.gpx
 gpsbabel -i gpx -f ${REFERENCE}/memory-map~mmo.gpx -o mmo -F ${TMPDIR}/memory-map~mmo.mmo
 gpsbabel -i mmo -f ${TMPDIR}/memory-map~mmo.mmo -o gpx -F ${TMPDIR}/memory-map~mmo~gpx.mmo
 
+#
+# Skyforce ascii files
+#
+gpsbabel -i skyforce -f ${REFERENCE}/skyforce_wpt.txt -o gpx -F ${TMPDIR}/skyforce_wpt.gpx
+compare ${REFERENCE}/skyforce_wpt.gpx ${TMPDIR}/skyforce_wpt.gpx
+gpsbabel -i skyforce -f ${REFERENCE}/route/skyforce_rte.txt -o gpx -F ${TMPDIR}/skyforce_rte.gpx
+compare ${REFERENCE}/route/skyforce_rte.gpx ${TMPDIR}/skyforce_rte.gpx
+gpsbabel -i skyforce -f ${REFERENCE}/track/skyforce_trk.txt -o gpx -F ${TMPDIR}/skyforce_trk.gpx
+compare ${REFERENCE}/track/skyforce_trk.gpx ${TMPDIR}/skyforce_trk.gpx
+
+gpsbabel -i skyforce \
+       -f ${REFERENCE}/skyforce_wpt.txt \
+       -f ${REFERENCE}/route/skyforce_rte.txt \
+       -f ${REFERENCE}/track/skyforce_trk.txt -o gpx -F ${TMPDIR}/skyforce.gpx
+compare ${REFERENCE}/skyforce.gpx ${TMPDIR}/skyforce.gpx
+
 
 exit 0
diff --git a/vecs.c b/vecs.c
index cebe19762c5206d02ae674373c0a322025c8ca4a..0e0863cecc6812f14bc161e2a37696170966cd34 100644 (file)
--- a/vecs.c
+++ b/vecs.c
@@ -152,6 +152,7 @@ extern ff_vecs_t jtr_vecs;
 #endif
 extern ff_vecs_t sbp_vecs;
 extern ff_vecs_t mmo_vecs;
+extern ff_vecs_t skyforce_vecs;
 
 static
 vecs_t vec_list[] = {
@@ -869,6 +870,12 @@ vecs_t vec_list[] = {
                 "Memory-Map Navigator overlay files (.mmo)",
                 "mmo"
         },
+        {
+               &skyforce_vecs,
+               "skyforce",
+               "Skymap / KMD150 ascii files",
+               NULL
+        },
         
 
 #endif // MAXIMAL_ENABLED